package com.samtech.commons;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean;
import org.apache.commons.beanutils.ConvertUtilsBean2;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.beanutils.converters.ArrayConverter;
import org.apache.commons.beanutils.converters.DateConverter;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.Assert;

/**
 * Utils - 系统
 */
public final class SystemSettingUtils {

	/**
	 * 日期格式配比
	 */
	public static final String[] DATE_PATTERNS = new String[] { "yyyy", "yyyy-MM", "yyyyMM", "yyyy/MM", "yyyy-MM-dd", "yyyyMMdd", "yyyy/MM/dd", "yyyy-MM-dd HH:mm:ss", "yyyyMMddHHmmss", "yyyy/MM/dd HH:mm:ss" };

	/**
	 * 
	 */
	public static final String SETTINGS_XML_PATH = "/settings.xml";
	/**
	 * BeanUtilsBean
	 */
	private static final BeanUtilsBean BEAN_UTILS;
	private static Setting settingInstance=null;
	static ReentrantLock synl=new ReentrantLock();
	static {
		ConvertUtilsBean convertUtilsBean = new ConvertUtilsBean2() {

			@Override
			public Converter lookup(Class<?> clazz) {
				Converter converter = super.lookup(clazz);
				if (converter != null) {
					return converter;
				}

				if (clazz.isEnum()) {
					EnumConverter enumConverter = new EnumConverter(clazz);
					super.register(enumConverter, clazz);
					return enumConverter;
				}
				if (clazz.isArray()) {
					Converter componentConverter = lookup(clazz.getComponentType());
					if (componentConverter != null) {
						ArrayConverter arrayConverter = new ArrayConverter(clazz, componentConverter, 0);
						arrayConverter.setOnlyFirstToString(false);
						super.register(arrayConverter, clazz);
						return arrayConverter;
					}
				}
				return super.lookup(clazz);
			}

		};

		DateConverter dateConverter = new DateConverter();
		dateConverter.setPatterns(DATE_PATTERNS);
		convertUtilsBean.register(dateConverter, Date.class);

		BEAN_UTILS = new BeanUtilsBean(convertUtilsBean);
	}

	/**
	 * 不可实例化
	 */
	private SystemSettingUtils() {
	}

	/**
	 * 获取系统设置
	 * 
	 * @return 系统设置
	 */
	@SuppressWarnings("unchecked")
	public static Setting getSetting() {
			if(settingInstance!=null)return settingInstance;
			synl.lock();
			try {
				Setting setting = new Setting();
				try {
					File settingsXmlFile = new ClassPathResource(SETTINGS_XML_PATH).getFile();
					Document document = new SAXReader().read(settingsXmlFile);
					List<org.dom4j.Node> elements = document.selectNodes("/settings/setting");
					for (org.dom4j.Node node : elements) {
						try {
							org.dom4j.Element element=(org.dom4j.Element)node;
							String name = element.attributeValue("name");
							String value = element.attributeValue("value");
							BEAN_UTILS.setProperty(setting, name, value);
						} catch (IllegalAccessException e) {
							throw new RuntimeException(e.getMessage(), e);
						} catch (InvocationTargetException e) {
							throw new RuntimeException(e.getMessage(), e);
						}
					}
					settingInstance=setting;
					return settingInstance;
				} catch (IOException e) {
					throw new RuntimeException(e.getMessage(), e);
				} catch (DocumentException e) {
					throw new RuntimeException(e.getMessage(), e);
				}
			}finally {
				synl.unlock();
			}
			
			
	}

	/**
	 * 设置系统设置
	 * 
	 * @param setting
	 *            系统设置
	 */
	@SuppressWarnings("unchecked")
	public static void setSetting(Setting setting) {
		Assert.notNull(setting);
		synl.lock();
		try {
			settingInstance=setting;
		}finally {
			synl.unlock();
		}
		try {
			File shopxxXmlFile = new ClassPathResource(SETTINGS_XML_PATH).getFile();
			Document document = new SAXReader().read(shopxxXmlFile);
			List<org.dom4j.Node> elements = document.selectNodes("/settings/setting");
			for (org.dom4j.Node node : elements) {
				try {
					org.dom4j.Element element=(org.dom4j.Element)node;
					String name = element.attributeValue("name");
					String value = BEAN_UTILS.getProperty(setting, name);
					Attribute attribute = element.attribute("value");
					attribute.setValue(value);
				} catch (IllegalAccessException e) {
					throw new RuntimeException(e.getMessage(), e);
				} catch (InvocationTargetException e) {
					throw new RuntimeException(e.getMessage(), e);
				} catch (NoSuchMethodException e) {
					throw new RuntimeException(e.getMessage(), e);
				}
			}

			XMLWriter xmlWriter = null;
			try {
				OutputFormat outputFormat = OutputFormat.createPrettyPrint();
				outputFormat.setEncoding("UTF-8");
				outputFormat.setIndent(true);
				outputFormat.setIndent("	");
				outputFormat.setNewlines(true);
				xmlWriter = new XMLWriter(new FileOutputStream(shopxxXmlFile), outputFormat);
				xmlWriter.write(document);
				xmlWriter.flush();
			} catch (FileNotFoundException e) {
				throw new RuntimeException(e.getMessage(), e);
			} catch (UnsupportedEncodingException e) {
				throw new RuntimeException(e.getMessage(), e);
			} catch (IOException e) {
				throw new RuntimeException(e.getMessage(), e);
			} finally {
				try {
					if (xmlWriter != null) {
						xmlWriter.close();
					}
				} catch (IOException e) {
				}
			}
		
		} catch (IOException e) {
			throw new RuntimeException(e.getMessage(), e);
		} catch (DocumentException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	
}